﻿using System;

using System.Collections.Generic;
using System.Text;
using System.Drawing;
using Silvermoon.Animations;
using System.Diagnostics;
using System.Threading;
using Silvermoon.Controls;
using Silvermoon.Controls.Interfaces;
using Silvermoon.Controls.Classes;
using Silvermoon.Controls.Base;
using Silvermoon.Windows;

namespace Silvermoon.Core
{
    /// <summary>
    /// Creates and coordinates messages between controls.
    /// </summary>
    public partial class MessageServer : IDisposable
    {
        #region constants

        const int SymbolKey = 235;
        const int LongPressDuration = 750;

        /// <summary>
        /// Unless the mouse is not dragged longer than this threshold in ms, ScrollEvents are not raised:
        /// </summary>
        public const int MaxDragDurationThreshold = 250;

        public const double VelocityThreshold = 0.1f;

        //public const double DragDistanceThreshold = 0.5d;

        #endregion
        #region ctor/tdor

        private MessageServer()
            : base()
        {
            holdTimer = new UITimer { Interval = LongPressDuration };
            holdTimer.Tick += new EventHandler(OnLongPressTick);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="MessageEngine"/> class.
        /// </summary>
        /// <param name="host">The host control for rendering.</param>
        /// <param name="inputControl">The control that has the input focus.</param>
        internal MessageServer(System.Windows.Forms.Control host, System.Windows.Forms.Control inputControl)
            : this()
        {
            this.Host = host;
            Screen = Screen.Current;

            host.MouseDown += OnMouseDown;
            host.MouseUp += OnMouseUp;
            host.MouseMove += OnMouseMove;
            host.KeyDown += new System.Windows.Forms.KeyEventHandler(OnKeyDown);
            host.KeyUp += new System.Windows.Forms.KeyEventHandler(OnKeyUp);
            host.KeyPress += new System.Windows.Forms.KeyPressEventHandler(OnKeyPress);

            if (inputControl != host)
            {
                inputControl.KeyDown += new System.Windows.Forms.KeyEventHandler(OnKeyDown);
                inputControl.KeyUp += new System.Windows.Forms.KeyEventHandler(OnKeyUp);
                inputControl.KeyPress += new System.Windows.Forms.KeyPressEventHandler(OnKeyPress);
            }
        }


        public void Dispose()
        {
            Host.MouseDown -= OnMouseDown;
            Host.MouseUp -= OnMouseUp;
            Host.MouseMove -= OnMouseMove;
            Host.KeyDown -= OnKeyDown;
            Host.KeyUp -= OnKeyUp;
            Host.KeyPress -= OnKeyPress;
        }

        #endregion
        #region fields

        private System.Windows.Forms.Control Host;
        private Screen Screen;
        public ControlCollection Controls { get; set; }
        internal Control FocusedControl { get; private set; }

        #endregion
        #region keyboard methods

        private void OnKeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
        {
            try
            {
                switch (e.KeyCode)
                {
                    case System.Windows.Forms.Keys.F1:
                        RaiseBackButton();
                        break;

                    case System.Windows.Forms.Keys.F2:
                        RaiseHomeButton();
                        break;
                }
                if ((int)e.KeyValue == SymbolKey)
                {
                    RaiseSymbolButton();
                    return;
                }
                if (FocusedControl != null)
                {
                    FocusedControl.OnKeyDown(e);
                }
            }
            catch (Exception ex)
            {
                if (Debugger.IsAttached) throw;
                Screen.Current.RaiseUnhandledException(ex);
            }
        }

        private void RaiseSymbolButton()
        {
            Window w = Screen.ActiveWindow;
            if (w != null) w.ToggleSymbols();
        }

        private void RaiseHomeButton()
        {
            Window w = Screen.ActiveWindow;
            if (w != null) w.GoHome();
        }

        private void RaiseBackButton()
        {
            Window w = Screen.ActiveWindow;
            if (w != null) w.GoBack();
        }

        private void OnKeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
        {
            try
            {
                if (FocusedControl != null) FocusedControl.OnKeyPress(e);
            }
            catch (Exception ex)
            {
                if (Debugger.IsAttached) throw;
                Screen.Current.RaiseUnhandledException(ex);
            }
        }


        private void OnKeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
        {
            try
            {
                if (FocusedControl != null) FocusedControl.OnKeyUp(e);
            }
            catch (Exception ex)
            {
                if (Debugger.IsAttached) throw;
                Screen.Current.RaiseUnhandledException(ex);
            }
        }

        public bool Focus(Control control)
        {
            if (control != null && !control.CanFocus) return false;
            if (FocusedControl != control)
            {
                Control fc = FocusedControl;
                FocusedControl = control;
                if (fc != null) fc.OnLostFocus();
                if (control != null) control.OnGotFocus();
                if (FocusChanged != null) FocusChanged(this, EventArgs.Empty);
                return true;
            }
            return true;
        }

        public void KeyPress(char key)
        {
            if (FocusedControl != null)
            {
                System.Windows.Forms.KeyPressEventArgs args = new System.Windows.Forms.KeyPressEventArgs(key);
                FocusedControl.OnKeyPress(args);
            }
        }

        #endregion

        #region events

        public event EventHandler FocusChanged;

        #endregion



        internal bool HasFocus(Control control)
        {
            return FocusedControl == control;
        }
    }
}
